package com.douing.ad.dsp.bidding.service.impl;


import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.alibaba.dubbo.config.annotation.Service;
import com.douing.ad.dsp.bidding.dto.AdRequestDto;
import com.douing.ad.dsp.bidding.dto.AdResponseDto;
import com.douing.ad.dsp.bidding.dto.AppRequestDto;
import com.douing.ad.dsp.bidding.dto.AppResponseDto;
import com.douing.ad.dsp.bidding.dto.MatchedCreativeDto;
import com.douing.ad.dsp.bidding.rtb.Common;
import com.douing.ad.dsp.bidding.rtb.CreativeMatch;
import com.douing.ad.dsp.bidding.rtb.GenerateResponse;
import com.douing.ad.dsp.bidding.rtb.PriceMatch;
import com.douing.ad.dsp.bidding.service.BiddingService;
import com.douing.ad.dsp.bidding.tj.utils.NodeData;
import com.douing.ad.dsp.bidding.tj.utils.TongJiUtil;
//import com.douing.ad.dsp.watch.api.monitor.enums.MonitorEnum;
import com.douing.common.dto.Request;
import com.douing.common.dto.Result;


@org.springframework.stereotype.Service
@Service
public class BiddingServiceImpl implements BiddingService {
    long starttime = 0;

    @Override
    public Result<AdResponseDto> adapterToBidding(Request<AdRequestDto> adRequestDto) {
        Map<String,NodeData> nodeDataMap = new HashMap<String,NodeData>();
        NodeData nodeData = new NodeData();
        nodeData.setRequestDate(new Date());
        //nodeData.setEntryNum(1);
        starttime = System.currentTimeMillis();
        Result<AdResponseDto> result = Result.create();
        try {
            if (adRequestDto == null) {
                result.setSuccess(false);
                result.setDescription("AdRequestDto is null!");
                Common.WriteLog("bidding error:AdRequestDto can't be null!");
                return result;
            }
            AdRequestDto request = adRequestDto.getData();
            if (request == null) {
                result.setSuccess(false);
                result.setDescription("request can't be null!");
                Common.WriteLog("bidding error:request can't be null!");
                return result;
            }
            if (request.getRequestId() == null || request.getRequestId().isEmpty()) {
                result.setSuccess(false);
                result.setDescription("requestid can't be null!");
                Common.WriteLog("bidding error:requestid can't be null!");
                return result;
            }
            AdResponseDto adResponse = new AdResponseDto();
            adResponse.setRequestId(request.getRequestId());
            result.setData(adResponse);
            
            if (Common.configInfo.getTrafficoff() == 1) {
                result.setSuccess(false);
                result.setDescription("traffic is off!");
                Common.WriteLog("Traffic is off!");
                return result;
            }
            
            if (request.getUser() == null) {
                result.setSuccess(false);
                result.setDescription("user can't be null!");
                Common.WriteLog("bidding error:user can't be null!");
                return result;
            }
            if (request.getUser().getUserId() == null || request.getUser().getUserId().isEmpty()) {
                result.setSuccess(false);
                result.setDescription("userid(cookie) can't be null!");
                Common.WriteLog("bidding error:userid(cookie) can't be null!");
                return result;
            }
            if (!request.getUser().getIp().isEmpty()) {
                Pattern pattern = Pattern.compile(
                        "\\b((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\.((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\.((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\.((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\b");
                Matcher matcher = pattern.matcher(request.getUser().getIp());
                if (!matcher.matches()) {
                    result.setSuccess(false);
                    result.setDescription("ip is error!");
                    Common.WriteLog("bidding error:ip is error!");
                    return result;
                }
            }
            if (request.getImp() == null) {
                result.setSuccess(false);
                result.setDescription("impression can't be null!");
                Common.WriteLog("bidding error:impression can't be null!");
                return result;
            }
            if (request.getImp().getBanner() == null || request.getImp().getBanner().getWidth() == null
                    || request.getImp().getBanner().getHeight() == null || request.getImp().getBanner().getWidth() <= 0
                    || request.getImp().getBanner().getHeight() <= 0) {
                result.setSuccess(false);
                result.setDescription("banner is null or bannerinfo error!");
                Common.WriteLog("bidding error:banner can't be null!");
                return result;
            }
            if (request.getImp().getAdSlotId() == null) {
                result.setSuccess(false);
                result.setDescription("AdSlotId can't be null!");
                Common.WriteLog("bidding error:AdSlotId can't be null!");
                return result;
            }
            if (request.getImp().getBidfloor() == null || request.getImp().getBidfloor() < 0) {
                result.setSuccess(false);
                result.setDescription("Bidfloor can't be null or below 0!");
                Common.WriteLog("bidding error:Bidfloor can't be null!");
                return result;
            }
            if (request.getChannelId() == null) {
                result.setSuccess(false);
                result.setDescription("channelid can't be null!");
                Common.WriteLog("bidding error:channelid can't be null!");
                return result;
            }
            if (request.getCategory() == null) {
                result.setSuccess(false);
                result.setDescription("category can't be null!");
                Common.WriteLog("bidding error:category can't be null!");
                return result;
            }
            if (request.getCostType() == null) {
                result.setSuccess(false);
                result.setDescription("costtype can't be null!");
                Common.WriteLog("bidding error:costtype can't be null!");
                return result;
            }

            request.setReqStartTime(starttime);
            // Common.SendMonitorDate(MonitorEnum.REQUEST);
            List<MatchedCreativeDto> matched = CreativeMatch.CreativeMatchImp(request, nodeData,nodeDataMap);
            result.setData(GenerateResponse.BuildResponse(request, PriceMatch.PriceMatchImp(request, matched, nodeData,nodeDataMap), nodeData,nodeDataMap));
            result.setSuccess(true);
            // Common.SendMonitorDate(MonitorEnum.RESPONSE);

        } catch (Exception ex) {
            result.setSuccess(false);
            // Common.SendMonitorDate(MonitorEnum.FAIL);
            Common.WriteError("bidding error:",ex);
            //Common.WriteError("bidding error:" + ex.getStackTrace());
        } finally {
            Common.WriteLog("bidding total time is " + (System.currentTimeMillis() - starttime));
            nodeData.setResponseDate(new Date());
            // 统计
            if (Common.configInfo.getTjoff() == 1) {
                // 关闭
            }else{
                long starttime = System.currentTimeMillis();
                for (Map.Entry<String,NodeData> entry : nodeDataMap.entrySet()) {  
                    entry.getValue().setResponseDate(new Date());
                    TongJiUtil.handle(entry.getValue()); 
                } 
                Common.WriteLog("TongJiUtil total time is " + (System.currentTimeMillis() - starttime));
            }
        }
        return result;
    }

    @Override
    public Result<AppResponseDto> appAdapterToBidding(Request<AppRequestDto> appRequestDto) {
        Map<String,NodeData> nodeDataMap = new HashMap<String,NodeData>();
        NodeData nodeData = new NodeData();
        nodeData.setRequestDate(new Date());
        //nodeData.setEntryNum(1);
        starttime = System.currentTimeMillis();
        Result<AppResponseDto> result = Result.create();
        try {
            if (appRequestDto == null) {
                result.setSuccess(false);
                result.setDescription("AdRequestDto is null!");
                Common.WriteLog("bidding error:AdRequestDto can't be null!");
                return result;
            }
            AppRequestDto request = appRequestDto.getData();
            if (request == null) {
                result.setSuccess(false);
                result.setDescription("request can't be null!");
                Common.WriteLog("bidding error:request can't be null!");
                return result;
            }
            if (request.getRequestId() == null || request.getRequestId().isEmpty()) {
                result.setSuccess(false);
                result.setDescription("requestid can't be null!");
                Common.WriteLog("bidding error:requestid can't be null!");
                return result;
            }
            AppResponseDto adResponse = new AppResponseDto();
            adResponse.setRequestId(request.getRequestId());
            result.setData(adResponse);
            
            if (Common.configInfo.getTrafficoff() == 1) {
                result.setSuccess(false);
                result.setDescription("traffic is off!");
                Common.WriteLog("Traffic is off!");
                return result;
            }
            
            if (request.getApp() == null) {
                result.setSuccess(false);
                result.setDescription("app can't be null!");
                Common.WriteLog("bidding error:app can't be null!");
                return result;
            }
            if (request.getDevice() == null) {
                result.setSuccess(false);
                result.setDescription("device can't be null!");
                Common.WriteLog("bidding error:device can't be null!");
                return result;
            }
            if (!request.getDevice().getIp().isEmpty()) {
                Pattern pattern = Pattern.compile(
                        "\\b((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\.((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\.((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\.((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\b");
                Matcher matcher = pattern.matcher(request.getDevice().getIp());
                if (!matcher.matches()) {
                    result.setSuccess(false);
                    result.setDescription("ip is error!");
                    Common.WriteLog("bidding error:ip is error!");
                    return result;
                }
            }
            if (request.getImp()==null && request.getImp().length>0) {
                result.setSuccess(false);
                result.setDescription("impression can't be null!");
                Common.WriteLog("bidding error:impression can't be null!");
                return result;
            }

            request.setReqStartTime(starttime);
            Map<String, List<MatchedCreativeDto>> matched = CreativeMatch.AppCreativeMatchs(request, nodeData,nodeDataMap);
            result.setData(GenerateResponse.BuildAppResponse(request, PriceMatch.AppPriceMatchImp(matched, nodeData,nodeDataMap), nodeData,nodeDataMap));
            result.setSuccess(true);

        } catch (Exception ex) {
            result.setSuccess(false);
            Common.WriteError("bidding error:",ex);
        } finally {
            Common.WriteLog("bidding total time is " + (System.currentTimeMillis() - starttime));
            //nodeData.setResponseDate(new Date());
            // 统计
            if (Common.configInfo.getTjoff() == 1) {
                // 关闭
            }else{
                long starttime = System.currentTimeMillis();
                for (Map.Entry<String,NodeData> entry : nodeDataMap.entrySet()) {  
                    entry.getValue().setResponseDate(new Date());
                    TongJiUtil.handle(entry.getValue()); 
                } 

                Common.WriteLog("TongJiUtil total time is " + (System.currentTimeMillis() - starttime));
            }
        }
        return result;
    }

}
